package com.example.spring32.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@RestController
public class TestController {

    @GetMapping("/test")
    public String test(){
        System.out.printf(Thread.currentThread().toString());


        List<CompletableFuture<List<Integer>>> completableFutures = new ArrayList<>();

        IntStream.range(0, 1000).forEach(i -> {

            CompletableFuture<List<Integer>> completableFuture = CompletableFuture
                    .supplyAsync(()->{
                try {
                    System.out.printf(Thread.currentThread().toString());
                    TimeUnit.MICROSECONDS.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return Stream.iterate(i, v -> v).limit(10).toList();
            }
            //, Executors.newVirtualThreadPerTaskExecutor()
            );

            completableFutures.add(completableFuture);
        });
        CompletableFuture<List<Integer>> cf = sequenceByAllOf(completableFutures);
        System.out.printf("cf = "+cf.join());
        return "ok";
    }

    public static <T> CompletableFuture<List<T>> sequenceByAllOf(
            List<CompletableFuture<List<T>>> completableFutures){
        return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]))
                .thenApply(
                        v -> completableFutures.stream()
                                .flatMap(listFuture -> listFuture.join().stream().filter(Objects::nonNull))
                                .toList()
                );
    }
}
